Optional Vertices.f

{

To do:
  draw using elements
  write data to a range in a buffer (finer control than VARRAY:[ )

}

Requires Kagi
Requires OpenGL
Requires Seki
Requires OpenGL\ARB-VBO
Requires GL-Tools
Requires Matrix-math
Requires SORA\Transformations

Only Forth Definitions

variable last-vertex-array
variable last-tcoord-array
variable last-color-array

0 Value vcolor
0 Value tcoord-x
0 Value tcoord-y
0 Value vpointer

:macro rgba   to vcolor ;
:macro tcoord  to tcoord-y to tcoord-x ;
:macro +u   +to tcoord-x ;
:macro +v   +to tcoord-y ;

{
: enable-vertex-arrays
   glEnableClientState( GL_VERTEX_ARRAY )
   glEnableClientState( GL_COLOR_ARRAY )
   glEnableClientState( GL_TEXTURE_COORD_ARRAY ) ;
}

\ -----

vocabulary [Vertex2D] also [Vertex2D] definitions
struct
  2 field ->x
  2 field ->y
  2 field ->z
  2 +  \ padding for alignment
  2 field ->u
  2 field ->v
  4 field ->rgba
previous definitions
end-struct /2D

also [Vertex2d]

: set-2D-pointers   ( addr/ofs -- )
   locals|  a/o  |
   glEnableClientState( GL_VERTEX_ARRAY )
   glEnableClientState( GL_COLOR_ARRAY )
   glEnableClientState( GL_TEXTURE_COORD_ARRAY )
   glVertexPointer( 3 GL_SHORT  16  a/o ->x )
   glTexCoordPointer( 2 GL_SHORT  16  a/o ->u )
   glColorPointer( 4 GL_UNSIGNED_BYTE  16  a/o ->rgba ) ;

{
code Vertex2D!a+   ( color ty tx z y x -- )
  [a] eax mov
  16bit: ebx 0 [eax] mov
  0 [ebp] ebx mov
  16bit: ebx 2 [eax] mov
  4 [ebp] ebx mov
  16bit: ebx 4 [eax] mov
  8 [ebp] ebx mov
  16bit: ebx 8 [eax] mov
  12 [ebp] ebx mov
  16bit: ebx 10 [eax] mov
  16 [ebp] ebx mov
  ebx 12 [eax] mov
  20 [ebp] ebx mov
  6 cells # ebp add
  /Vertex2D # eax add
  eax [a] mov
  ret end-code
}

\ Follows pairing rules and uses inlining for best speed
icode vertex2d ( x y z -- )
  &of vpointer [u] eax mov
  0 [ebp] ecx mov
  16bit: ebx 4 [eax] mov    \ z
  4 [ebp] ebx mov
  16bit: ecx 2 [eax] mov    \ y
  16bit: ebx 0 [eax] mov    \ x

  &of tcoord-x [u] ecx mov
  &of tcoord-y [u] ebx mov
  &of vcolor [u] edx mov
  16bit: ecx 8 [eax] mov    \ u
  16bit: ebx 10 [eax] mov   \ v
  edx 12 [eax] mov          \ color

  2 cells [ebp] ebx mov
  16 # eax add
  3 cells # ebp add
  eax &of vpointer [u] mov
  ret end-code

Create 2D   /2D , ' set-2D-pointers ,

icode point2d ( x y -- )
  &of vpointer [u] eax mov
  0 [ebp] ecx mov
  16bit: ebx 2 [eax] mov    \ y
  16bit: ecx 0 [eax] mov    \ x
  1 cells [ebp] ebx mov
  4 # eax add
  2 cells # ebp add
  eax &of vpointer [u] mov
  ret end-code

: set-2D-point-pointers   ( addr/ofs -- )
   locals|  a/o  |
   glEnableClientState( GL_VERTEX_ARRAY )
   glDisableClientState( GL_COLOR_ARRAY )
   glDisableClientState( GL_TEXTURE_COORD_ARRAY )
   glVertexPointer( 2 GL_SHORT  4  a/o  ) ;

Create 2D-Points   4 , ' set-2D-point-pointers ,
\ -----

:macro vtype>size   @ ;

: set-vertex-pointers   (  vertex-type addr/ofs -- )
   swap cell+ @ execute ;

0 Value mapped-vbo

-? 0 value xt
-? 0 value v
-? 0 value s
\ Populate a VBO with data of a given size.  Address of the buffer is placed in A.
\  Creates a new buffer each time, which lets the old buffer finish rendering without blocking.
\  If the OpenGL driver can map the VBO to client mem, rendering speed is 15% faster on my machine.
:[] varray:[  (  size vbo xt -- [ A=addr -- ]  )
  to xt to v to s
  s v map-vbo ( a! xt catch -varray throw ) ?dup 0= if
    s temp:[ dup >q a!  xt catch   glBufferSubDataARB( GL_ARRAY_BUFFER_ARB   0   s   q> )  throw  ;]
  else
    a! xt catch unmap-vbo throw
  then ;
